%{
#include <stdio.h>
#include <iostream>
#include <set>
#include <ctype.h>

using namespace std;

set<string> *conjunto_def;

void tolowerStr(char * str){
	int i=0;
	
	while(str[i]!=0){
		str[i] = tolower(str[i]);
		i++;
	}
	
}

extern "C"
{
		
        int yylex(void); 
        extern FILE* yyin;
        int yywrap()
        {
                return 1;
        }
        
}


void yyerror(const char *str)
{
        fprintf(stderr,"error: %s\n",str);
}

FILE * salida;

%}


%token TOKDEFINE TOKMOVE TOKSCALE TOKROTATE TOKREPEAT TOKBOX TOKCIRCLE TOKABRIRPARENTESIS TOKCERRARPARENTESIS


%union 
{
        float real;
        char* name;
}

//%token <real> REAL
%left <real> REAL
%token <name> NAME



%%

graficos:
	|
	graficos grafico
	|
	graficos definicion
	;	
grafico:
	atomico
	|
	repeticion
	|
	rotacion
	|
	mover
	|
	escalar
	;
definicion:
	TOKDEFINE NAME {
		
		char *name= $2;
		tolowerStr(name);
		
		//Chequeamos si ya estaba defindo
		if (conjunto_def->find(name) != conjunto_def->end()){
					
					
					char error_msg[50];
					sprintf(error_msg,"Intenta definir %s cuando ya estaba definida antes.", name);
					yyerror(error_msg);
					
				//por si lo de arriba no corta ejecucion
				while(1);
		}
		//Lo guardo en el conjunto
				conjunto_def->insert(name);
		
				printf("/%s {",name);
		
		
		} grafico {{printf("} def ");}}
	;
	
repeticion:
	TOKREPEAT REAL REAL REAL {printf("gsave %d { ",(int) $2);} grafico {printf("%f %f translate } repeat grestore ",$3,$4);}
	;

rotacion:
	TOKROTATE REAL {printf("gsave %f rotate ",$2);} grafico {printf(" grestore ");}
	;
	
mover:
	TOKMOVE REAL REAL {printf("gsave %f %f translate ",$2,$3);} grafico {printf(" grestore ");}
	;
	
escalar:
	TOKSCALE REAL REAL {printf("gsave %f %f scale ",$2,$3);} grafico {printf(" grestore ");} 
	;
		
atomico:
	TOKBOX REAL REAL {printf("gsave %f %f scale box grestore ",$2,$3);}
	|
	TOKCIRCLE REAL {printf("gsave %f %f scale circ grestore ",$2,$2);}
	|
	TOKABRIRPARENTESIS graficos TOKCERRARPARENTESIS
	|
	NAME {
		
		char *name= $1;
		tolowerStr(name);
		
		if (conjunto_def->find(name) != conjunto_def->end()){
			printf("gsave %s grestore ",name);
		}else{
			char error_msg[50];
			sprintf(error_msg,"Usa %s sin haberlo definido antes.", name);
			yyerror(error_msg);
					
			
		}
		
		}
	;
	
%%


  
main(int argc,char *argv[])
{	
	
	//Creamos el conjunto de definiciones
    set<string> conjunto;
    conjunto_def = &conjunto;
    
    
	if (argc>1){
		printf("Modo archivo \n");
	//printf("cantargs:%d \n filename:%s\n",argc, argv[1]);
	
		
		
		FILE * entrada=fopen(argv[1],"r");
        yyin=entrada;
        
        string nombre = ((string) argv[1])+".eps";
        freopen (nombre.c_str(),"w",stdout);
                
               
        
        
    } else{
		  printf("Modo consola \n");
		  yyin= NULL;
		  
  }
    
    
        printf( "%%Prologo generico.\n \
		5 dict begin\n \
		/box {\n \
		\t0 0 moveto 0 1 lineto 1 1 lineto 1 0 lineto closepath fill\n\
		} def\n\n\
		/circ {\n \
		\t0 0 1 0 360 arc closepath fill\n\
		} def\n\
		%%Fin prologo. Comienzo grafico.\n\n");

        yyparse();
        
        printf("\nend\nshowpage");
} 

